package com.hmall.order.service.impl;

import cn.hutool.core.lang.generator.SnowflakeGenerator;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.hmall.client.ItemClient;
import com.hmall.client.UserClient;
import com.hmall.context.BaseContext;
import com.hmall.dto.OrderDTO;
import com.hmall.order.mapper.OrderLogisticsMapper;
import com.hmall.order.mapper.OrderMapper;
import com.hmall.order.service.IOrderDetailService;
import com.hmall.pojo.*;
import com.hmall.order.service.IOrderService;
import io.seata.core.context.RootContext;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.concurrent.FailureCallback;
import org.springframework.util.concurrent.SuccessCallback;

import java.lang.ref.SoftReference;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Service
@Slf4j
public class OrderService extends ServiceImpl<OrderMapper, Order> implements IOrderService {
    @Autowired
    private IOrderDetailService iOrderDetailService;
    @Autowired
    private SnowflakeGenerator snowflakeGenerator;
    @Autowired
    private ItemClient itemClient;
    @Autowired
    private UserClient userClient;
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderLogisticsMapper orderLogisticsMapper;
    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 创建订单
     * @param orderDTO
     * @return
     */
    @Override
    @GlobalTransactional //分布式事务入口
    @Transactional  //  本地数据库事务
    public Long createOrder(OrderDTO orderDTO) {
        log.info("开始创建订单：{}",orderDTO);
        //获取当前用户id
        Long userId = BaseContext.getCurrentId();

        //根据雪花算法生成订单id【注意 前端精度丢失问题，必须使用字符串来返回】
        Long id = snowflakeGenerator.next();

        //根据itemId查询商品信息
        Item item = itemClient.getById(orderDTO.getItemId());

        //基于商品价格、购买数量计算商品总价：totalFee
        Long totalFee = item.getPrice() * orderDTO.getNum();

        //封装Order对象，初识status为未支付
        Order order = new Order();
        order.setId(id);
        order.setTotalFee(totalFee);
        order.setPaymentType(orderDTO.getPaymentType());
        order.setUserId(userId);
        order.setStatus(1);
        order.setCreateTime(new Date());
        order.setUpdateTime(new Date());

        //将Order写入数据库tb_order表中
        orderMapper.insert(order);

        //将商品信息、orderId信息封装为OrderDetail对象，写入tb_order_detail表
        OrderDetail orderDetail = new OrderDetail();
        orderDetail.setOrderId(order.getId());
        orderDetail.setItemId(item.getId());
        orderDetail.setNum(orderDTO.getNum());
        orderDetail.setTitle(item.getName());
        orderDetail.setPrice(totalFee);
        orderDetail.setSpec(item.getSpec());
        orderDetail.setImage(item.getImage());
        orderDetail.setCreateTime(new Date());
        orderDetail.setUpdateTime(new Date());

        iOrderDetailService.save(orderDetail);

        //根据addressId查询user-service服务，获取地址信息
        Address address = userClient.findAddressById(orderDTO.getAddressId());

        //将地址封装为OrderLogistics对象，写入tb_order_logistics表
        OrderLogistics orderLogistics = new OrderLogistics();
        BeanUtils.copyProperties(address,orderLogistics);
        orderLogistics.setOrderId(order.getId());
        orderLogistics.setLogisticsNumber(UUID.randomUUID().toString().substring(0,10));
        orderLogistics.setLogisticsCompany("顺丰物流");
        orderLogistics.setPhone(address.getMobile());
        orderLogistics.setCreateTime(new Date());
        orderLogistics.setUpdateTime(new Date());

        orderLogisticsMapper.insert(orderLogistics);

        //调用item-service的减库存接口
        itemClient.deductItemNum(item.getId(),orderDTO.getNum());

        //调用user-service的扣款接口
        userClient.deductMoney(order.getUserId(),totalFee);

        //调用sendMessage方法清理超时未支付订单
        sendMessage(order.getId());

        //返回结果
        return order.getId();
    }

    /**
     * 清理超时未支付订单
     * @param id
     */
    public void sendMessage(Long id){
        //消费者确认机制 publish -- confirm
        log.info("清理超时未支付订单。。。");
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());

        correlationData.getFuture().addCallback(success -> {
            if (success.isAck()) {
                log.info("消息发送成功!!!ID:{}",correlationData.getId());
            }else {
                log.error("消息发送失败！！！ID：{},原因：{}",correlationData.getId(),success.getReason());
            }
        }, failure -> {
            log.error("消息发送异常，ID：{}，原因：{}",correlationData.getId(),failure.getMessage());
        });

        Message message = MessageBuilder.withBody(id.toString().getBytes(StandardCharsets.UTF_8))
                .setDeliveryMode(MessageDeliveryMode.PERSISTENT)
                .setHeader("x-delay", 5000)//测试
                //.setHeader("x-delay", 1,800,000)//30分钟
                .build();

        rabbitTemplate.convertAndSend("delay.direct","delay",message,correlationData);
        log.info("消息发送成功了！！！");
    }
}
